import { isObject } from "@utils";
import * as Geom from "ol/geom";
import * as Projection from "ol/proj";
import * as Sphere from "ol/sphere";
import { LngLat } from "./types";
/**
 * @description: 格式化不同类型经纬度的数据结构
 * @param {LngLat} lnglat 经纬度
 * @returns {Array<number>}
 */
export const parseLngLat = (lnglat: LngLat): [number, number] | undefined => {
  if (Array.isArray(lnglat)) {
    let [longitude, latitude] = lnglat;
    longitude = parseFloat(String(longitude));
    latitude = parseFloat(String(latitude));
    if (Number.isNaN(longitude) || Number.isNaN(latitude)) {
      return undefined;
    }
    return [longitude, latitude];
  }
  if (
    !lnglat ||
    Object.getPrototypeOf(lnglat).toString() !== "[object Object]"
  ) {
    return undefined;
  }
  const {
    longitude: _longitude,
    lng,
    latitude: _latitude,
    lat,
  } = lnglat as any;
  const longitude = parseFloat(String(_longitude ?? lng));
  const latitude = parseFloat(String(_latitude ?? lat));
  if (Number.isNaN(longitude) || Number.isNaN(latitude)) {
    return undefined;
  }
  return [longitude, latitude];
};
/**
 * @description: 请求瓦片 Blob 数据
 * @private
 * @param {Object} options 配置项
 * @returns {Promise<Blob>}
 */
export const _fetchTileByBlob = (options: {
  url: string;
  method?:
    | "get"
    | "post"
    | "put"
    | "delete"
    | "GET"
    | "POST"
    | "PUT"
    | "DELETE";
  headers?: Record<string, string>;
}): Promise<Blob> =>
  new Promise<Blob>((resolve, reject) => {
    const { method = "get", url, headers = {} } = options;
    const xhr = new XMLHttpRequest();

    xhr.addEventListener("loadend", ({ target }) => {
      if (target instanceof XMLHttpRequest) {
        if (
          target.response instanceof Blob &&
          target.response.type.startsWith("image/")
        ) {
          resolve(target.response);
        } else {
          reject(new Error("瓦片内容无法解析"));
        }
      } else {
        reject(new Error("氢气失败"));
      }
    });
    xhr.addEventListener("error", (e) => {
      reject(e);
    });

    xhr.responseType = "blob";
    xhr.open(method.toLocaleUpperCase(), url);
    if (isObject(headers)) {
      Object.keys(headers).forEach((key) => {
        xhr.setRequestHeader(key, headers[key].toString());
      });
    }

    xhr.send();
  });
/**
 * @description: 获取两个坐标之间的距离，单位米
 * @param {LngLat} start
 * @param {LngLat} end
 * @returns {number}
 * @example  getDistance([118.96703676772272, 32.15055251514587], [117.96703676772272, 33.15055251514587])
 */
export const getDistance = (start: LngLat, end: LngLat): number => {
  const startLngLat = parseLngLat(start);
  const endLngLat = parseLngLat(end);
  if (!startLngLat || !endLngLat) {
    return 0;
  }
  return Sphere.getDistance(startLngLat, endLngLat);
};

/**
 * @description: 获取几何形状的面积，单位平方米
 * @param {Geom.Geometry|Array<Array<LngLat>>} geometry 几何形状或者经纬度数组
 * @returns {number}
 * @example

 */
export const getArea = (geometry: Geom.Geometry | LngLat[][]): number => {
  if (geometry instanceof Geom.Geometry) {
    return Sphere.getArea(geometry, {
      projection: Projection.get("EPSG:4326") as Projection.Projection,
    });
  } else if (Array.isArray(geometry)) {
    return Sphere.getArea(
      new Geom.Polygon(
        geometry.map(
          (line) =>
            line
              .map((lnglat) => parseLngLat(lnglat))
              .filter((lnglat) => lnglat !== undefined) as number[][]
        )
      ),
      {
        projection: Projection.get("EPSG:4326") as Projection.Projection,
      }
    );
  }

  return 0;
};
